package sicau.carManager.controller;


import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import sicau.carManager.Util.LicensePlateRecognitionUtil.LicensePlateRecognition;
import sicau.carManager.Util.TokenUtil.MD5Util;
import sicau.carManager.Util.TokenUtil.TokenUtil;
import sicau.carManager.Util.TokenUtil.UUIDUtil;
import sicau.carManager.entity.Admin;
import sicau.carManager.entity.FixedCarInformation;
import sicau.carManager.entity.ViolationInformation;
import sicau.carManager.exception.ApiException;
import sicau.carManager.result.R;
import sicau.carManager.service.AdminService;
import sicau.carManager.service.FixedCarInformationService;
import sicau.carManager.service.ViolationInformationService;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author ITcz
 * @since 2021-02-05
 */
@RestController
@RequestMapping("/admin")
@CrossOrigin
public class AdminController {

    @Autowired
    AdminService adminService;

    @Autowired
    FixedCarInformationService fixedCarInformationService;

    @Autowired
    ViolationInformationService violationInformationService;

    @Autowired
    RestTemplate restTemplate;

    @Value("${server.port}")
    String SERVER_PORT;

    @Value("${ip.hostAddress}")
    String HOST_ADDRESS;

    @Value("${ip.imagePath}")
    String imagePath;

    /**
     *   定义时间格式为精确到分
     */
    private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");


    /**
     * 每天凌晨3点自动清楚所有登录的token信息
     */
    @Scheduled(cron = "0 0 3 * * ?")
    private void cleanTokenDaily(){
        TokenUtil.deleteAll();
    }

    /**
    * 每天凌晨检查违章记录，删除超过一年的记录
    * */
    @Scheduled(cron = "0 0 0 * * ?")
    private void cleanMoreThanOneYearViolationInformation(){ violationInformationService.cleanMoreThanOneYearViolationInformation();}

    @ApiOperation("通用登录接口")
    @PostMapping("/loginIn")
    public R loginIn(@ApiParam("账号") @RequestParam("userName")String account, @ApiParam("密码") @RequestParam("password")String password){
        if (account == null || password == null) {
            return R.error(0, "账号或密码为空");
        }
        Admin admin = adminService.loginIn(account, password);
        if (admin != null) {
            //生成一段随机值token，放入token工具类的Hashmap里，并把token，校区，管理员权限返回给前端
            String token = TokenUtil.setToken(admin);
            HashMap resMap =new HashMap();
            resMap.put("token", token);
            resMap.put("campus", admin.getCampus());
            resMap.put("authority", admin.getAuthority());
            return R.ok(resMap);
        }
        return R.error(500100, "账号或密码错误");
    }

    @ApiOperation("通用退出登录接口，在header里传入用户token信息即可")
    @GetMapping("/loginOut")
    public R loginOut(HttpServletRequest request){
        String token = request.getHeader("token");
        TokenUtil.removeToken(token);
        return R.ok("退出登录成功");
    }

    @ApiOperation("显示个人账号信息,什么参数都不用传")
    @GetMapping("/get/message")
    public R getMessage(Admin admin){
        HashMap res = new HashMap();
        res.put("message", admin);
        return R.ok(res);
    }


    @ApiOperation("修改个人账号信息")
    @PostMapping("/update/admin")
    public R updateAdmin(Admin admin, @ApiParam("账号信息从这里面选：jobNumber，name，password") @RequestBody  Map<String,Object> map){
        if (map == null) {
            return R.error(500301, "输入管理员信息为空！");
        }
        if (map.containsKey("jobNumber")) {
            admin.setJobNumber((String) map.get("jobNumber"));
        }if (map.containsKey("name")) {
            admin.setName((String) map.get("name"));
        }if (map.containsKey("password")) {
            //密码加密存储
            String dbPassword = MD5Util.inputPassToDbPass((String) map.get("password"));
            admin.setPassword(dbPassword);
        }
        boolean b = adminService.updateOne(admin);
        if (!b) {
            return R.error(500301, "数据库更新信息出现错误！");
        }
        return R.ok("修改成功!");
    }


    @ApiOperation("上传个人信息中的照片,修改照片也用此接口")
    @PostMapping("/upload/personal/image")
    public R uploadPersonalImg(@ApiParam("MultipartFile类型的图片信息(用form data方式上传)") @RequestParam("imgFile") MultipartFile file,
                            Admin admin) throws IOException {
        if(file.isEmpty()) {
            return R.error(500401, "上传图片为空");
        }
        Integer id = admin.getId();
        byte[] bytes = file.getBytes();
        int result = adminService.putImage(bytes, id);
        if (result > 0) {
            return R.ok("上传图片成功!");
        }else {
            return R.error(500402, "上传失败!");
        }
    }

    @ApiOperation("拉取个人信息中的照片，调用此接口返回照片的二进制流bites[]")
    @GetMapping("/download/personal/image")
    public R downloadPersonalImage(Admin admin){
        byte[] bites = adminService.pull(admin.getId());
        if (bites == null) {
            return R.ok("未上传照片");
        }
        HashMap resMap = new HashMap();
        resMap.put("image", bites);
        return R.ok(resMap);
    }

    @PostMapping("plateRecognition/byPhoto")
    @ApiOperation("根据上传照片识别车牌")
    public R plateRecognitionByPhoto(@ApiParam("MultipartFile类型的图片信息(用form data方式上传)") @RequestParam("imgFile") MultipartFile file) throws IOException {
        if(file.isEmpty()) {
            return R.error(500401, "待识别图片为空");
        }
        byte[] fileBytes = file.getBytes();
        //传入图片二进制流，返回识别后的车牌
        String licensePlate = LicensePlateRecognition.licensePlateByByte(fileBytes);
        return R.ok(licensePlate);
    }

    /**
    * 有固定车，临时车两种可能，需要依次判断
    * */
    @GetMapping("query/information/by/licensePlate")
    @ApiOperation("通过车牌查询车辆信息")
    public R queryByLicensePlate(Admin admin, @ApiParam("车牌") @RequestParam("licensePlate") String licensePlate) {
        HashMap resMap = new HashMap();
        resMap.put("车牌", licensePlate);
        resMap.put("违章次数", 0);
        resMap.put("车辆性质：", "临时车");
        //如果有违章记录则更新违章次数
        Integer integer = violationInformationService.selectViolationNumByPlateNum(licensePlate, admin.getCampus());
        if (integer != null) {
            resMap.replace("违章次数", integer);
        }
        //判断是不是固定车
        FixedCarInformation fixedCarInformation = fixedCarInformationService.selectCarByPlateNum(licensePlate, admin.getCampus());
        if (fixedCarInformation != null) {
            //修改车辆性质
            resMap.replace("车辆性质：", "固定车/内部车");
            resMap.put("申请人姓名：", fixedCarInformation.getApplicant());
            resMap.put("车主姓名：", fixedCarInformation.getLicenseOwner());
            resMap.put("申请人单位：", fixedCarInformation.getUnit());
            resMap.put("车主与申请人关系：", fixedCarInformation.getRelationshipWithApplicant());
        }
        return R.ok(resMap);
    }

    /**
    * 文件配置最大为15MB
    * */
    @PostMapping("upload/violation/information")
    @ApiOperation("上传保存违章记录")
    public R uploadViolationInformation(Admin admin, @ApiParam("MultipartFile类型的图片信息(用form data方式上传)") @RequestParam(name = "imgFile", required = false) MultipartFile file,
                                        @ApiParam("违章车牌号") @RequestParam("license_plate_number") String licensePlateNumber ,
                                        @ApiParam("违章地点") @RequestParam("place") String place ,
                                        @ApiParam("违章原因") @RequestParam("reason") String reason) throws IOException {
        if (file == null || file.isEmpty()) {
            throw new ApiException("请先选择违章图片!");
        }

        //存放公告图片的文件夹地址
        String path = "/usr/carManager/javaImage/";
        File imgFile = new File(path);
        if (!imgFile.exists()) {
            //不存在文件则创建一个目录，路径名由当前File对象指定
            imgFile.mkdirs();
        }

        //以UUID作为图片名称前缀
        String imageNamePre = UUIDUtil.uuid();
        //判断图片后缀(格式)
        String fileName = file.getOriginalFilename();
        String[] split = fileName.split("[.]");
        String huizhui = "." + split[split.length-1];
        //拼接处完整的图片名
        String imageName = imageNamePre + huizhui;

        //在选定文件中写入图片
        try (FileOutputStream fos = new FileOutputStream(new File(path + imageName))) {
            fos.write(file.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        //value 的值为前端渲染图片的绝对路径(图片从/usr/local/javaImage/路径下取)
        String urlPrefix = HOST_ADDRESS + ":" + SERVER_PORT + "/";
        String imageUrl = urlPrefix + imageName;

        ViolationInformation violationInformation = new ViolationInformation();
        violationInformation.setRecorderName(admin.getName());
        violationInformation.setRecorderNumber(admin.getJobNumber());
        violationInformation.setCampus(admin.getCampus());
        if (reason == null || place == null || licensePlateNumber == null) {
            return R.error(500604, "map参数名有误或值为空！");
        }
        violationInformation.setReason(reason);
        violationInformation.setPlace (place);
        violationInformation.setLicensePlateNumber(licensePlateNumber);
        violationInformation.setImageUrl(imageUrl);
        violationInformation.setImageName(imageName);
        //获取当前时间，精确到分
        violationInformation.setTime(LocalDateTime.now().withNano(0).withSecond(0));
        //根据车牌查询是否为固定车，如果是则把联系电话一起记录
        FixedCarInformation fixedCarInformation = fixedCarInformationService.selectCarByPlateNum(licensePlateNumber, admin.getCampus());
        if (null != fixedCarInformation) {
            violationInformation.setPhoneNumber(fixedCarInformation.getPhoneNumber());
        }
        violationInformationService.save(violationInformation);

        return R.ok("上传完成");
    }


}

